From 838188511cb2085d8980956b270cc68ed9911102 Mon Sep 17 00:00:00 2001
From: Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>
Date: Thu, 4 Aug 2016 12:26:56 +0200
Subject: [PATCH 11/12] ntpd: postpone hostname resolution if fails on startup

Signed-off-by: Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>
---
 networking/ntpd.c | 130 +++++++++++++++++++++++++++---------------------------
 1 file changed, 64 insertions(+), 66 deletions(-)

diff --git a/networking/ntpd.c b/networking/ntpd.c
index b7fa5dce9..c6d07adac 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -155,6 +155,7 @@
 #define RETRY_INTERVAL    32    /* on send/recv error, retry in N secs (need to be power of 2) */
 #define NOREPLY_INTERVAL 512    /* sent, but got no reply: cap next query by this many seconds */
 #define RESPONSE_INTERVAL 16    /* wait for reply up to N secs */
+#define HOSTNAME_INTERVAL  4    /* hostname lookup failed. Wait N secs for next try */
 
 /* Step threshold (sec). std ntpd uses 0.128.
  */
@@ -293,6 +294,7 @@ typedef struct {
 
 typedef struct {
 	len_and_sockaddr *p_lsa;
+	char             *p_hostname;
 	char             *p_dotted;
 	int              p_fd;
 	int              datapoint_idx;
@@ -318,7 +320,6 @@ typedef struct {
 	datapoint_t      filter_datapoint[NUM_DATAPOINTS];
 	/* last sent packet: */
 	msg_t            p_xmt_msg;
-	char             p_hostname[1];
 } peer_t;
 
 
@@ -791,27 +792,17 @@ reset_peer_stats(peer_t *p, double offset)
 }
 
 static void
-resolve_peer_hostname(peer_t *p, int loop_on_fail)
-{
-	len_and_sockaddr *lsa;
-
- again:
-	lsa = host2sockaddr(p->p_hostname, 123);
-	if (!lsa) {
-		/* error message already emitted by host2sockaddr() */
-		if (!loop_on_fail)
-			return;
-//FIXME: do this to avoid infinite looping on typo in a hostname?
-//well... in which case, what is a good value for loop_on_fail?
-		//if (--loop_on_fail == 0)
-		//	xfunc_die();
-		sleep(5);
-		goto again;
+resolve_peer_hostname(peer_t *p) {
+	len_and_sockaddr *lsa = host2sockaddr(p->p_hostname, 123);
+	if (lsa) {
+		if (p->p_lsa) {
+			free(p->p_lsa);
+			free(p->p_dotted);
+		}
+		p->p_lsa = lsa;
+		p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
 	}
-	free(p->p_lsa);
-	free(p->p_dotted);
-	p->p_lsa = lsa;
-	p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
+	set_next(p, lsa ? 0 : HOSTNAME_INTERVAL);
 }
 
 static void
@@ -820,28 +811,29 @@ add_peers(const char *s)
 	llist_t *item;
 	peer_t *p;
 
-	p = xzalloc(sizeof(*p) + strlen(s));
-	strcpy(p->p_hostname, s);
-	resolve_peer_hostname(p, /*loop_on_fail=*/ 1);
+	p = xzalloc(sizeof(*p));
+	p->p_hostname = xstrdup(s);
+	resolve_peer_hostname(p);
 
 	/* Names like N.<country2chars>.pool.ntp.org are randomly resolved
 	 * to a pool of machines. Sometimes different N's resolve to the same IP.
 	 * It is not useful to have two peers with same IP. We skip duplicates.
 	 */
-	for (item = G.ntp_peers; item != NULL; item = item->link) {
-		peer_t *pp = (peer_t *) item->data;
-		if (strcmp(p->p_dotted, pp->p_dotted) == 0) {
-			bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted);
-			free(p->p_lsa);
-			free(p->p_dotted);
-			free(p);
-			return;
+	if (p->p_lsa)
+		for (item = G.ntp_peers; item != NULL; item = item->link) {
+			peer_t *pp = (peer_t *) item->data;
+			if (pp->p_lsa && strcmp(p->p_dotted, pp->p_dotted) == 0) {
+				bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted);
+				free(p->p_hostname);
+				free(p->p_lsa);
+				free(p->p_dotted);
+				free(p);
+				return;
+			}
 		}
-	}
 
 	p->p_fd = -1;
 	p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
-	p->next_action_time = G.cur_time; /* = set_next(p, 0); */
 	reset_peer_stats(p, STEP_THRESHOLD);
 
 	llist_add_to(&G.ntp_peers, p);
@@ -2378,44 +2370,50 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
 		for (item = G.ntp_peers; item != NULL; item = item->link) {
 			peer_t *p = (peer_t *) item->data;
 
-			if (p->next_action_time <= G.cur_time) {
-				if (p->p_fd == -1) {
-					/* Time to send new req */
-					if (--cnt == 0) {
-						VERB4 bb_error_msg("disabling burst mode");
-						G.polladj_count = 0;
-						G.poll_exp = MINPOLL;
+			if (p->p_lsa) {
+
+				if (p->next_action_time <= G.cur_time) {
+					if (p->p_fd == -1) {
+						/* Time to send new req */
+						if (--cnt == 0) {
+							VERB4 bb_error_msg("disabling burst mode");
+							G.polladj_count = 0;
+							G.poll_exp = MINPOLL;
+						}
+						send_query_to_peer(p);
+					} else {
+						/* Timed out waiting for reply */
+						close(p->p_fd);
+						p->p_fd = -1;
+						/* If poll interval is small, increase it */
+						if (G.poll_exp < BIGPOLL)
+							adjust_poll(MINPOLL);
+						timeout = poll_interval(NOREPLY_INTERVAL);
+						bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
+								p->p_dotted, p->reachable_bits, timeout);
+
+						/* What if don't see it because it changed its IP? */
+						if (p->reachable_bits == 0)
+							resolve_peer_hostname(p);
+
+						set_next(p, timeout);
 					}
-					send_query_to_peer(p);
-				} else {
-					/* Timed out waiting for reply */
-					close(p->p_fd);
-					p->p_fd = -1;
-					/* If poll interval is small, increase it */
-					if (G.poll_exp < BIGPOLL)
-						adjust_poll(MINPOLL);
-					timeout = poll_interval(NOREPLY_INTERVAL);
-					bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
-							p->p_dotted, p->reachable_bits, timeout);
-
-					/* What if don't see it because it changed its IP? */
-					if (p->reachable_bits == 0)
-						resolve_peer_hostname(p, /*loop_on_fail=*/ 0);
-
-					set_next(p, timeout);
 				}
-			}
+
+				if (p->p_fd >= 0) {
+					/* Wait for reply from this peer */
+					pfd[i].fd = p->p_fd;
+					pfd[i].events = POLLIN;
+					idx2peer[i] = p;
+					i++;
+				}
+
+			} else
+				resolve_peer_hostname(p);
 
 			if (p->next_action_time < nextaction)
 				nextaction = p->next_action_time;
 
-			if (p->p_fd >= 0) {
-				/* Wait for reply from this peer */
-				pfd[i].fd = p->p_fd;
-				pfd[i].events = POLLIN;
-				idx2peer[i] = p;
-				i++;
-			}
 		}
 
 		timeout = nextaction - G.cur_time;
-- 
2.11.0

